package start.spring.basic.dynamic;

import java.time.Duration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.bind.BindResult;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;

import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.JedisPoolConfig;
import start.spring.basic.exception.common.CommonException;
import start.spring.basic.util.common.StringUtil;

/**
 * ****************************************************************************
 * redis注册类
 *
 * @author(作者)：xuyongyun	
 * @author(复审人)：	Administrator 2018年8月22日
 * @version(版本)1.0
 * @since 1.0
 ******************************************************************************
 */
@Slf4j
@RefreshScope
@Repository
public class DynamicRedisRegister implements EnvironmentAware {
	
	private static final String SPLIT_VALUE = ",";
	
	//redis默认配置值
	private int maxTotal = 50;
	private int maxWaitMillis = 6000;
	private int maxIdl = 10;
	private int timeout = 0;
	
	@Autowired
	DynamicJdbc dao;
	
	/**
	 * 缓存RedisTemplate
	 */
    private static Map<String, Map<String,StringRedisTemplate>> redisTemplateMap = new HashMap<>();
    
    /**
	 * 缓存RedisTemplate
	 */
    private static Map<String, RedisStandaloneConfiguration> redisStandaloneConfigMap = new HashMap<>();
	
    @Override
	public void setEnvironment(Environment environment) {
    	log.info("DynamicRedisRegister开始初始化redis配置！");
        initCustomRedis(environment);
	}

	/**
	 * 初始化redis
	 *	
	 * @param env
	 * @since           1.0
	 */
	private void initCustomRedis(Environment env) {
		//读取默认数据库配置
		Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(env);
		Binder binder = new Binder(sources);
		BindResult<Properties> dbBindResult = binder.bind("spring.redis", Properties.class);
		Properties properties = dbBindResult.get();
		
		//读取配置文件获取更多redis配置
        String redisNames = properties.getProperty("customnames");
        if(!StringUtil.isEmpty(redisNames)) {
        	String[] redisNameArray = redisNames.split(SPLIT_VALUE);
			for (String redisName : redisNameArray) {
				String sql = "SELECT REDIS_ID, IP, PORT, PWD, MAX_TOTAL, MAX_IDLE, MAX_WAIT_MILLIS, TIMEOUT FROM GG_PZ_REDIS WHERE REDIS_ID like ? ";
				String[] prams = {redisName + "%"};
				List<Map<String,Object>> redisConfList = dao.query(DsConstant.SYSCONFIG, sql, prams);
				
                if(redisConfList!=null&&redisConfList.size()>0) {
                	for(Map<String,Object> configMap:redisConfList) {
                		StringRedisTemplate redisTemplate = buildTemplate(configMap);
                		Map<String,StringRedisTemplate> tmpMap = redisTemplateMap.get(redisName);
                		if(tmpMap==null) {
                			tmpMap = new HashMap<>();
                		}
                		tmpMap.put(String.valueOf(configMap.get("REDIS_ID")), redisTemplate);
        				redisTemplateMap.put(redisName,tmpMap);
                	}
    				log.info("redis:{}初始化完毕！", redisName);
                }else {
                	log.info("redis:{}的配置未在数据库获取到！",redisName);
                }
			}
        }else {
        	log.info("属性文件未配置需要初始化的redis！");
        }
	}

	private StringRedisTemplate buildTemplate(Map<String,Object> redisConfigMap) {
		try {
			
			if(!StringUtil.isEmpty(String.valueOf(redisConfigMap.get("MAX_TOTAL")))) {
				maxTotal = Integer.parseInt(String.valueOf(redisConfigMap.get("MAX_TOTAL")).trim());
			}
			if(!StringUtil.isEmpty(String.valueOf(redisConfigMap.get("MAX_WAIT_MILLIS")))) {
				maxWaitMillis =Integer.parseInt(String.valueOf(redisConfigMap.get("MAX_WAIT_MILLIS")).trim());
			}
			if(!StringUtil.isEmpty(String.valueOf(redisConfigMap.get("MAX_IDLE")))) {
				maxIdl =Integer.parseInt(String.valueOf(redisConfigMap.get("MAX_IDLE")).trim());
			}

			if(!StringUtil.isEmpty(String.valueOf(redisConfigMap.get("TIMEOUT")))) {
				timeout =Integer.parseInt(String.valueOf(redisConfigMap.get("TIMEOUT")).trim());
			}

			JedisPoolConfig poolConfig=new JedisPoolConfig();
			poolConfig.setMaxTotal(maxTotal);
			poolConfig.setMaxWaitMillis(maxWaitMillis);
			poolConfig.setMaxIdle(maxIdl);
			poolConfig.setTestOnBorrow(false);
			poolConfig.setTestWhileIdle(true);
			poolConfig.setTimeBetweenEvictionRunsMillis(30000);
			poolConfig.setMinEvictableIdleTimeMillis(600000);
			
	        //获得默认的连接池构造器(怎么设计的，为什么不抽象出单独类，供用户使用呢) 有毒
	        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcb =
	                (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration.builder()
	                .connectTimeout(Duration.ofSeconds(timeout))
	                .readTimeout(Duration.ofSeconds(timeout));
	        //指定jedisPoolConifig来修改默认的连接池构造器（真麻烦，滥用设计模式！） ！！！！
	        jpcb.poolConfig(poolConfig);
	        //通过构造器来构造jedis客户端配置
	        JedisClientConfiguration jedisClientConfiguration = jpcb.build();

			
			RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
			redisStandaloneConfiguration.setHostName(redisConfigMap.get("IP").toString().trim());
			redisStandaloneConfiguration.setPort(Integer.parseInt(String.valueOf(redisConfigMap.get("PORT")).trim()));
			if(!StringUtil.isEmpty(String.valueOf(redisConfigMap.get("PWD")))){
				redisStandaloneConfiguration.setPassword(redisConfigMap.get("PWD").toString().trim());
			}
			
			JedisConnectionFactory jedisConnectionFactory = new JedisConnectionFactory(redisStandaloneConfiguration,jedisClientConfiguration);
			jedisConnectionFactory.afterPropertiesSet();
			
			//缓存redis配置
			redisStandaloneConfigMap.put(redisConfigMap.get("REDIS_ID").toString().trim(), redisStandaloneConfiguration);
			
			StringRedisTemplate stringRedisTemplate = new StringRedisTemplate(jedisConnectionFactory);
			return stringRedisTemplate;
		}catch(Exception e) {
			log.error("redis初始化出错!",e);
		}
		return null;
	}
	
	public Map<String,StringRedisTemplate> getRedisMap(String redisKey) {
		if(StringUtil.isEmpty(redisKey)) {
			throw new CommonException("请指定redis key！");
		}else {
			Map<String,StringRedisTemplate> stringRedisTemplateMap = redisTemplateMap.get(redisKey);
			if(stringRedisTemplateMap == null){
				throw new CommonException("redis:" + redisKey + "的连接信息未配置！");
			}
			return stringRedisTemplateMap;
		}
	}
	
	public RedisStandaloneConfiguration getRedisStandaloneConfiguration(String redisKey) {
		return redisStandaloneConfigMap.get(redisKey);
	}
}
